import React, { useEffect, useState, useRef } from 'react';
import { cloneDeep } from 'lodash';
import { Collapse, Button, Tooltip, Popconfirm, InputNumber } from '@block/plug';
import { ListOperateType, transferItem } from '@src/utils';
import { UnusualPage } from '..';
import './CollapseList.scss';

interface IProps<T> extends Collapse {
  /** 标题 */
  title?: (val: T, index?: number) => string | React.ReactNode;
  /** 是否是多个 */
  multiple?: boolean;
  /** 最大长度 */
  maxLength?: number;
  /** 折叠面板列表数据 */
  data: Array<T>;
  /** 列表唯一标识 */
  keyField?: string;
  /** 编辑状态 */
  mode: Mode;
  /** 头部选择控件 */
  renderHeaderSelect?: (val: T, index?: number) => React.ReactNode;
  /** 内容控件 */
  renderContent?: (val: T, index?: number) => React.ReactNode;
  /** 自定义类名 */
  className?: string;
  /** 空展示文案 */
  emptyText?: string;
  /** 操作数据 */
  onChange: (val: Array<T>) => void;
  /** 新增初始数据 */
  addInitData: () => T;
  /** 转移弹窗自定义渲染（使用后组件内部转移数据处理失效，需通过自定义转移回调自行处理） */
  renderTransfer?: React.ReactNode;
  /** 转移自定义数据处理回调 */
  onTransfer?: (index: number, data: Array<T>) => void;
  /** 转移弹层显示/隐藏事件 */
  onTransferVisibleChange?: (visible: boolean) => void;
  /** 添加按钮禁用（使用后maxLength属性失效） */
  addDisable?: (val: T, index: number, data: Array<T>) => boolean;
  /** 上移按钮禁用 */
  upDisable?: (val: T, index: number, data: Array<T>) => boolean;
  /** 下移按钮禁用 */
  downDisable?: (val: T, index: number, data: Array<T>) => boolean;
  /** 转移按钮禁用 */
  transferDisable?: (val: T, index: number, data: Array<T>) => boolean;
  /** 删除按钮禁用 */
  deleteDisable?: (val: T, index: number, data: Array<T>) => boolean;

  getContainer?: () => HTMLElement;
}

/**
 * 可折叠列表
 */

const CollapseList = <T,>(props: IProps<T>) => {
  const {
    title,
    multiple,
    maxLength,
    data,
    onChange,
    keyField,
    addInitData,
    renderHeaderSelect,
    renderContent,
    mode,
    className,
    emptyText,
    renderTransfer,
    onTransfer,
    onTransferVisibleChange,
    addDisable,
    upDisable,
    downDisable,
    transferDisable,
    deleteDisable,
    getContainer,
    ...other
  } = props;

  const [renderDataList, setRenderDataList] = useState<T[]>(data ?? []); // 当multiple为true时，内部缓存渲染数据

  /** 转移的目标索引 */
  const transferToIndex = useRef<number>();

  /**
   * 折叠面板列表操作事件，仅在multiple为true时有用
   * @param e event
   * @param type 操作类型
   * @param index 需要添加的索引下标
   */
  const handleOperate = (e: MouseEvent, type: ListOperateType, index?: number, toIndex?: number) => {
    e?.stopPropagation();

    // 创建新引用，否则setState不会更新
    const newRenderDataList = cloneDeep(renderDataList);

    switch (type) {
      case ListOperateType.add: {
        if (Number.isInteger(index)) newRenderDataList?.splice(index + 1, 0, addInitData());
        else newRenderDataList?.push(addInitData());
        onChange(newRenderDataList);
        break;
      }
      case ListOperateType.up: {
        const [item] = newRenderDataList.splice(index, 1);
        newRenderDataList.splice(index - 1, 0, item);
        onChange(newRenderDataList);
        break;
      }
      case ListOperateType.down: {
        const [item] = newRenderDataList.splice(index, 1);
        newRenderDataList.splice(index + 1, 0, item);
        onChange(newRenderDataList);
        break;
      }
      case ListOperateType.transfer: {
        if (onTransfer) onTransfer(index, newRenderDataList);
        else {
          if (toIndex > newRenderDataList.length) toIndex = newRenderDataList.length;
          if (toIndex > 0) {
            transferItem(newRenderDataList, index, toIndex - 1);
          }
          onChange(newRenderDataList);
        }
        break;
      }
      case ListOperateType.delete: {
        newRenderDataList.splice(index, 1);
        onChange(newRenderDataList);
        break;
      }
      default:
        break;
    }
  };

  useEffect(() => {
    if (multiple) {
      setRenderDataList((data as T[]) ?? []);
    }
  }, [data]);

  /**
   * 渲染单个折叠面板
   * @param itemData 折叠面板的数据
   * @param index 数组下标，当multiple为false时可缺省
   * @returns 折叠面板卡片
   */
  const renderCollapseItem = (itemData: T, index?: number) => {
    const transferDisabled = transferDisable
      ? transferDisable(itemData, index, renderDataList)
      : renderDataList?.length <= 1;

    return (
      <Collapse.Item
        className="collapse-list-item"
        key={itemData[keyField]}
        code={index ?? -1}
        title={
          <div className="card-header">
            <div className="card-header-left">
              {title && <span className="card-title">{title(itemData, index)}</span>}
              <span className="card-content" onClick={(e) => e.stopPropagation()}>
                {renderHeaderSelect(itemData, index)}
              </span>
            </div>
            <div className="right-btns">
              {mode === 'edit' && multiple && (
                <div onClick={(e) => e.stopPropagation()}>
                  <Tooltip message="添加" autoDestory getContainer={getContainer}>
                    <Button
                      shape="circle"
                      icon="add"
                      size="small"
                      ghost
                      hoverShape
                      disabled={
                        addDisable ? addDisable(itemData, index, renderDataList) : renderDataList.length >= maxLength
                      }
                      onClick={(e) => handleOperate(e, ListOperateType.add, index)}
                    />
                  </Tooltip>
                  <Tooltip message="上移" autoDestory getContainer={getContainer}>
                    <Button
                      shape="circle"
                      icon="arrow-up"
                      size="small"
                      ghost
                      hoverShape
                      disabled={upDisable ? upDisable(itemData, index, renderDataList) : index === 0}
                      onClick={(e) => handleOperate(e, ListOperateType.up, index)}
                    />
                  </Tooltip>
                  <Tooltip message="下移" autoDestory getContainer={getContainer}>
                    <Button
                      shape="circle"
                      icon="arrow-down"
                      size="small"
                      ghost
                      hoverShape
                      disabled={
                        downDisable ? downDisable(itemData, index, renderDataList) : index === renderDataList.length - 1
                      }
                      onClick={(e) => handleOperate(e, ListOperateType.down, index)}
                    />
                  </Tooltip>
                  <Popconfirm
                    trigger="click"
                    className="collapse-list-transfer-popover"
                    autoDestory
                    placement="topRight"
                    // TODO：组件库问题，修复后可删
                    align={{ offset: [7, -7] }}
                    getContainer={getContainer}
                    onVisibleChange={(visible) => {
                      if (onTransferVisibleChange) onTransferVisibleChange(visible);
                      else if (visible) transferToIndex.current = null;
                    }}
                    message={
                      renderTransfer ?? (
                        <div className="collapse-list-transfer">
                          移动至第
                          <InputNumber
                            className="input-number"
                            onChange={(val) => {
                              transferToIndex.current = val;
                            }}
                            min={1}
                            precision={0}
                            controls={false}
                          />
                          位
                        </div>
                      )
                    }
                    onOk={() => handleOperate(null, ListOperateType.transfer, index, transferToIndex.current)}
                  >
                    <div
                      className="btn-block"
                      style={{
                        pointerEvents: `${transferDisabled ? 'none' : 'auto'}`,
                      }}
                    >
                      <Tooltip message="移动至" autoDestory zIndex={1029} getContainer={getContainer}>
                        <Button
                          shape="circle"
                          icon="sortupanddown-o"
                          size="small"
                          ghost
                          hoverShape
                          disabled={transferDisabled}
                        />
                      </Tooltip>
                    </div>
                  </Popconfirm>
                  <Popconfirm
                    trigger="click"
                    message="确认删除吗？删除后不可恢复"
                    autoDestory
                    align={{ offset: [7, -8] }}
                    placement="topRight"
                    getContainer={getContainer}
                    onOk={() => handleOperate(null, ListOperateType.delete, index)}
                  >
                    <div
                      className="btn-block"
                      style={{
                        pointerEvents: `${
                          deleteDisable && deleteDisable(itemData, index, renderDataList) ? 'none' : 'auto'
                        }`,
                      }}
                    >
                      <Tooltip message="删除" autoDestory zIndex={1029} getContainer={getContainer}>
                        <Button
                          shape="circle"
                          icon="delete-o"
                          size="small"
                          ghost
                          hoverShape
                          disabled={deleteDisable ? deleteDisable(itemData, index, renderDataList) : false}
                        />
                      </Tooltip>
                    </div>
                  </Popconfirm>
                </div>
              )}
            </div>
          </div>
        }
      >
        {renderContent(itemData, index)}
      </Collapse.Item>
    );
  };

  /** 折叠面板允许多个时的渲染 */
  const renderMultipleCollapse = () => {
    if (renderDataList?.length > 0) {
      return (
        <Collapse className={`collapse-list ${className}`} {...other}>
          {renderDataList?.map((item, index) => renderCollapseItem(item, index))}
        </Collapse>
      );
    }
    return (
      <UnusualPage
        className="empty"
        tips={null}
        detail={
          <span>
            {emptyText}
            {mode === 'edit' && (
              <span>
                ，
                <Button type="primary" shape="text" onClick={(e) => handleOperate(e, ListOperateType.add)}>
                  点击添加
                </Button>
              </span>
            )}
          </span>
        }
      />
    );
  };

  /** 只有单个折叠面板时的渲染 */
  const renderSingleCollapse = () => {
    const [dataItem] = data ?? [];
    if (mode === 'view' && !dataItem) {
      return <UnusualPage className="empty" tips={null} detail={<span>{emptyText}</span>} />;
    }
    return (
      <Collapse className={`collapse-list ${className}`} {...other}>
        {renderCollapseItem(dataItem)}
      </Collapse>
    );
  };

  return multiple ? renderMultipleCollapse() : renderSingleCollapse();
};

CollapseList.defaultProps = {
  keyField: 'id',
  maxLength: Infinity,
  emptyText: '暂无数据',
};

export default CollapseList;
